package com.ldy.guava;

import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.*;
import com.google.common.io.Files;
import com.google.common.util.concurrent.*;
import com.sun.istack.internal.Nullable;
import org.junit.Assert;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * GuavaTest<br>
 * 版权: Copyright (c) 2011-2018<br>
 * 公司: 活力天汇<br>
 *
 * @author: 刘德咏<br>
 * @date: 2018-04-11<br>
 */
public class TestGuava {
    @Test
    public void testJoiner() {
        /*
         on:制定拼接符号，如：test1-test2-test3 中的 “-“ 符号
         skipNulls()：忽略NULL,返回一个新的Joiner实例
         useForNull(“Hello”)：NULL的地方都用字符串”Hello”来代替
        */
        StringBuilder sb=new StringBuilder();
        Joiner.on(",").skipNulls().appendTo(sb,"Hello","guava");
        System.out.println(sb);
        System.out.println(Joiner.on(",").useForNull("none").join(1,null,3));
        System.out.println(Joiner.on(",").skipNulls().join(Arrays.asList(1,2,3,4,null,6)));
        Map<String,String> map=new HashMap<>();
        map.put("key1","value1");
        map.put("key2","value2");
        map.put("key3","value3");
        System.out.println(Joiner.on(",").withKeyValueSeparator("=").join(map));
        System.out.println(Joiner.on(",").withKeyValueSeparator("ldy").join(map));
        System.out.println(Joiner.on("_").join("CITY", "WUH", "CN"));
    }

    @Test
    public void testSplitter() {
 /*
         on():指定分隔符来分割字符串
         limit():当分割的子字符串达到了limit个时则停止分割
         fixedLength():根据长度来拆分字符串
         trimResults():去掉子串中的空格
         omitEmptyStrings():去掉空的子串
         withKeyValueSeparator():要分割的字符串中key和value间的分隔符,分割后的子串中key和value间的分隔符默认是=
        */
        System.out.println(Splitter.on(",").limit(3).trimResults().split(" a,  b,  c,  d"));//[ a, b, c,d]
        System.out.println(Splitter.fixedLength(3).split("1 2 3"));//[1 2,  3]
        System.out.println(Splitter.on(" ").omitEmptyStrings().splitToList("1  2 3"));
        System.out.println(Splitter.on(",").omitEmptyStrings().split("1,,,,2,,,3"));//[1, 2, 3]
        System.out.println(Splitter.on(" ").trimResults().split("1 2 3")); //[1, 2, 3],默认的连接符是,
        System.out.println(Splitter.on(";").withKeyValueSeparator(":").split("a:1;b:2;c:3"));//{a=1, b=2, c=3}

//        String regExp = "ws";
//        String regExp = "ws$sw";
        String regExp = "";
        Iterable<String> iterable = Splitter.on("$").trimResults().split(regExp);
        Iterator<String> iterator = iterable.iterator();
        while (iterator.hasNext()) {
            System.out.println(" AND LOCATE(?, constent) > 0");
            System.out.println(iterator.next());
        }
    }

    @Test
    public void testMultiSet() {
        Multiset<String> set= LinkedHashMultiset.create();
        set.add("a");
        set.add("a");
        set.add("a");
        set.add("a");
        set.add("b", 2);
        set.setCount("c",5); //添加或删除指定元素使其在集合中的数量是count
        System.out.println(set.count("a")); //给定元素在Multiset中的计数
        System.out.println(set);
        System.out.println(set.size()); //所有元素计数的总和,包括重复元素
        System.out.println(set.elementSet().size()); //所有元素计数的总和,不包括重复元素
        set.clear(); //清空集合
        System.out.println(set);
    }

    @Test
    public void testMultiMap() throws Exception {
        Multimap<String,Integer> map= HashMultimap.create(); //Multimap是把键映射到任意多个值的一般方式
        map.put("a",1); //key相同时不会覆盖原value
        map.put("a",2);
        map.put("a",3);
        System.out.println(map); //{a=[1, 2, 3]}
        System.out.println(map.get("a")); //返回的是集合
        System.out.println(map.size()); //返回所有”键-单个值映射”的个数,而非不同键的个数
        System.out.println(map.keySet().size()); //返回不同key的个数
        Map<String,Collection<Integer>> mapView=map.asMap();
        System.out.println(mapView);
    }

    @Test
    public void testBiMap() {
        BiMap<String,String> biMap= HashBiMap.create();
        biMap.put("sina","sina.com");
        biMap.put("qq","qq.com");
        biMap.put("sina","sina.cn"); //会覆盖原来的value
       /*
         在BiMap中,如果你想把键映射到已经存在的值，会抛出IllegalArgumentException异常
         如果对特定值,你想要强制替换它的键，请使用 BiMap.forcePut(key, value)
        */
//        biMap.put("tecent","qq.com"); //抛出异常
        biMap.forcePut("tecent","qq.com"); //强制替换key
        System.out.println(biMap);
        System.out.println(biMap.inverse().get("sina.com")); //通过value找key
        System.out.println(biMap.inverse().inverse()==biMap); //true
    }

    @Test
    public void testTable() {
//记录学生在某门课上的成绩
        Table<String,String,Integer> table= HashBasedTable.create();
        table.put("jack","java",100);
        table.put("jack","c",90);
        table.put("mike","java",93);
        table.put("mike","c",100);
        Set<Table.Cell<String,String,Integer>> cells=table.cellSet();
        for (Table.Cell<String,String,Integer> cell : cells) {
            System.out.println(cell.getRowKey()+" "+cell.getColumnKey()+" "+cell.getValue());
        }
        System.out.println(table.row("jack"));
        System.out.println(table);
        System.out.println(table.rowKeySet());
        System.out.println(table.columnKeySet());
        System.out.println(table.values());
        System.out.println(table.cellSet());
    }

    @Test
    public void testCollection2() {
        // 可以过滤集合中的item
        List<String> list= Lists.newArrayList("moon","dad","refer","son");
        Collection<String> palindromeList= Collections2.filter(list, input -> {
//            return new StringBuilder(input).reverse().toString().equals(input); //找回文串
            return input.startsWith("mo");
        });
        list.stream().filter(input -> input.startsWith("re"));
        System.out.println(palindromeList);
    }

    @Test
    public void testFuture() throws Exception{
        //将ExecutorService装饰成ListeningExecutorService
        ListeningExecutorService service= MoreExecutors.listeningDecorator(
                Executors.newCachedThreadPool());

        //通过异步的方式计算返回结果
        ListenableFuture<String> future=service.submit(() -> {
            System.out.println("call execute..");
            System.out.println(Thread.currentThread().getName());
            int sum = 0;
            for (int i=0; i< 10000000; i++) {
                sum += i;
            }
            return sum + "";
        });

        //有两种方法可以执行此Future并执行Future完成之后的回调函数
        future.addListener(() -> {  //该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行
            try {
                System.out.println("result: "+future.get(10000l, TimeUnit.MILLISECONDS));
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        },service);

        Futures.addCallback(future, new FutureCallback<String>() {
            @Override
            public void onSuccess(@Nullable String result) {
                System.out.println("callback result: "+result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.out.println(t.getMessage());
            }
        },service);
    }

    @Test
    public void testOptional() {
        String user = "a";
        String defaultString = Optional.ofNullable(user).
                flatMap(u -> Optional.of(u.replace("a", "b"))).
                flatMap(u1 -> Optional.of(u1.replace("b", "c"))).
                orElse("default");
        Assert.assertEquals(defaultString, "default");

    }

    @Test
    public void testIO() throws Exception{
        File file=new File(System.getProperty("user.dir") + File.separator + "a.txt");
//        writeFile("test", file);
        System.out.println(readFile(file));
//        copyFile(file, new File(System.getProperty("user.dir") + "a.txt"));
    }

    //写文件
    private void writeFile(String content,File file) throws IOException {
        if (!file.exists()){
            file.createNewFile();
        }
        Files.write(content.getBytes(Charsets.UTF_8),file);
    }

    //读文件
    private List<String> readFile(File file) throws IOException {
        if (!file.exists()){
            return ImmutableList.of(); //避免返回null
        }
        return Files.readLines(file,Charsets.UTF_8);
    }

    //文件复制
    private void copyFile(File from,File to) throws IOException {
        if (!from.exists()){
            return;
        }
        if (!to.exists()){
            to.createNewFile();
        }
        Files.copy(from,to);
    }
}
